#include <stdio.h>
#include <dirent.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "rfs-defs.h"
int sdmax;

int create_socket(long port);
int close_socket(int sd);
int read_conf();
int rls(PACKAGE*);
int rcd(PACKAGE*);
long get(PACKAGE*);
long put(PACKAGE*);
int exit_client(PACKAGE* package);
int waiting_for_connections(int sd);

int main(int argc, char *argv[]) {
    fd_set sockets_set, temp_s_set;

    if (read_conf() == ERROR) {
        perror("No se ha podido leer el archivo de configuración del Servidor. Se aborta la operación.\n");
        exit(ERROR);
    };
    // Inicializo el servidor.
    if ((sd = create_socket(port)) < 0) {
        perror("ERROR INICIALIZANDO SERVIDOR: ");
        exit(ERROR);
    }
    sdmax = sd;
    printf("Servidor inicializado.\n");
    FD_ZERO(&sockets_set);
    FD_SET(sd, &sockets_set);

    PACKAGE *package;
    package = malloc(sizeof (PACKAGE));
    int socket = 0, i;

    while (1) {
        temp_s_set = sockets_set;

        if (select(sdmax + 1, &temp_s_set, NULL, NULL, NULL) == ERROR) {
            perror("ERROR en la llamada select()");
            exit(1);
        }

        for (i = 0; i <= sdmax; i++) {
            if (FD_ISSET(i, &temp_s_set)) {
                if (i == sd) {
                    if ((socket = waiting_for_connections(sd)) < 0) {
                        perror("ERROR ESPERANDO NUEVO CLIENTE: ");
                    } else {
                        FD_SET(socket, &sockets_set); // añadir al conjunto maestro
                        if (socket > sdmax) { // actualizar el máximo
                            sdmax = socket;
                        }
                    }
                
                } else {
                    /* Read from the socket */
                    read(i, package, sizeof (PACKAGE));
                    package->to = i;
                    switch (package->op) {
                        case RLS:
                            rls(package);
                            break;
                        case RCD:
                            rcd(package);
                            break;
                        case GET:
                            get(package);
                            break;
                        case PUT:
                            put(package);
                            break;
                        case QUIT:
                            printf("Cerrando cliente...\n");
                            exit_client(package);
                            FD_CLR(i, &sockets_set);
                            printf("Cliente cerrado...\n");
                            break;
                        default:
                            close_socket(i);
                            FD_CLR(i, &sockets_set);
                            break;
                    }
                }
            }

        }
    }
}